#include "libservice.h"

int service_deploy(char * serviceName, char * serviceWsdl, char * physicalPath,
		char * uuid) {
	xmlDoc *doc = NULL;
	xmlNode *root = NULL;
	xmlNode *service = NULL;
	xmlNode *serviceNew = NULL;

	char * service_file;
	config_get_string(&service_file, "SERVICES_FILE");

	pthread_mutex_t cs_mutex = PTHREAD_MUTEX_INITIALIZER;
	pthread_mutex_lock(&cs_mutex);
	//enter critical section

	doc = xmlReadFile(service_file, NULL, XML_PARSE_NOWARNING);

	if (!doc) {

		doc = xmlNewDoc("1.0");
		root = xmlNewNode(NULL, "services");
		xmlDocSetRootElement(doc, root);

	}

	root = xmlDocGetRootElement(doc);

	service = root ->children;

	while (service) {
		//check if the give wsdlAddress was already registered
		if (xmlStrEqual(xmlGetProp(service, "addressWsdl"), serviceWsdl)) {
			fprintf(stderr, "service.c: %s already deployed\n", uuid);
			break;
		}
		service = service->next;
	}

	if (!service) {

		serviceNew = xmlNewNode(NULL, "service");
		xmlNewProp(serviceNew, "name", serviceName);
		xmlNewProp(serviceNew, "addressWsdl", serviceWsdl);
		xmlNewProp(serviceNew, "path", physicalPath);
		xmlNewProp(serviceNew, "uuid", uuid);
		xmlAddChild(root, serviceNew);

		fprintf(stderr, "service.c: %s now deployed\n", serviceName);
	} else {
		xmlSetProp(service, "name", serviceName);
		xmlSetProp(service, "addressWsdl", serviceWsdl);
		xmlSetProp(service, "path", physicalPath);
		xmlSetProp(service, "uuid", uuid);

		fprintf(stderr, "service.c: %s now deployed again\n", serviceName);
	}

	xmlSaveFile(service_file, doc);

	pthread_mutex_unlock(&cs_mutex);
	pthread_mutex_destroy(&cs_mutex);
	//leave critical section

	xmlFreeDoc(doc);

	return 0;

}

int service_undeploy(char * serviceName, char * uuid) {
	xmlDoc *doc = NULL;
	xmlDoc *docNew = NULL;

	xmlNode *root = NULL;
	xmlNode *rootNew = NULL;
	xmlNode *service = NULL;

	int registered = 0;

	char * service_file;
	config_get_string(&service_file, "SERVICES_FILE");

	pthread_mutex_t cs_mutex = PTHREAD_MUTEX_INITIALIZER;
	pthread_mutex_lock(&cs_mutex);
	// enter critical section

	doc = xmlReadFile(service_file, NULL, XML_PARSE_NOWARNING);

	if (!doc) {

		fprintf(stderr, "service.c: deployment file %s doesn't exist\n",
				service_file);
		return 1;
	}

	root = xmlDocGetRootElement(doc);
	service = root ->children;

	docNew = xmlNewDoc("1.0");
	rootNew = xmlNewNode(NULL, "services");
	xmlDocSetRootElement(docNew, rootNew);

	while (service) {
		//traverse factory list, add factories to the new list
		//except the one which should be removed

		if (!xmlStrEqual(xmlGetProp(service, "uuid"), uuid) || !xmlStrEqual(
				xmlGetProp(service, "name"), serviceName)) {
			xmlAddChild(rootNew, xmlCopyNode(service, 1));

		} else {
			fprintf(stderr, "service.c: %s with id %s now undeployed\n",
					serviceName, uuid);
			registered = 1;
		}
		service = service->next;
	}
	if (!registered) {
		fprintf(stderr, "service.c: %s with id %s not deployed\n", serviceName,
				uuid);
	}

	xmlSaveFile(service_file, docNew);

	pthread_mutex_unlock(&cs_mutex);
	pthread_mutex_destroy(&cs_mutex);
	//leave critical section

	xmlFreeDoc(doc);
	xmlFreeDoc(docNew);

	return 0;

}

int service_set_uuid(char **uuid) {
	*uuid = (char *) malloc(37);
	uuid_t tmp;
	uuid_generate(tmp);
	uuid_unparse(tmp, *uuid);
	return 0;
}

/* Subtract the `struct timeval' values X and Y,
 storing the result in RESULT.
 Return 1 if the difference is negative, otherwise 0.  */

int timeval_subtract(struct timeval *result, struct timeval *x,
		struct timeval *y) {
	/* Perform the carry for the later subtraction by updating y. */
	if (x->tv_usec < y->tv_usec) {
		int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
		y->tv_usec -= 1000000 * nsec;
		y->tv_sec += nsec;
	}
	if (x->tv_usec - y->tv_usec > 1000000) {
		int nsec = (y->tv_usec - x->tv_usec) / 1000000;
		y->tv_usec += 1000000 * nsec;
		y->tv_sec -= nsec;
	}

	/* Compute the time remaining to wait.
	 tv_usec  is certainly positive. */
	result->tv_sec = x->tv_sec - y->tv_sec;
	result->tv_usec = x->tv_usec - y->tv_usec;

	/* Return 1 if result is negative. */
	return x->tv_sec < y->tv_sec;
}

//retrieve string variable from configuration file

int config_get_string(char ** value, const char * name) {
	xmlDoc *doc = NULL;
	xmlNode *root = NULL;
	xmlNode *parameter = NULL;

	doc = xmlReadFile(configuration_file, NULL, XML_PARSE_NOWARNING);

	if (!doc) {
		fprintf(stderr, "service.c: configuration file doesn't exist\n");
		return 1;
	}

	root = xmlDocGetRootElement(doc);
	parameter = root ->children;
	*value = NULL;
	while (parameter) {
		if (xmlStrEqual(xmlGetProp(parameter, "name"), name)) {
			*value = malloc(256);
			strcpy(*value, xmlGetProp(parameter, "value"));
			break;
		}
		parameter = parameter->next;
	}

	xmlFreeDoc(doc);

	return 0;
}

//retrieve int variable from configuration file

int config_get_int(int * value, const char * name) {
	xmlDoc *doc = NULL;
	xmlNode *root = NULL;
	xmlNode *parameter = NULL;

	doc = xmlReadFile(configuration_file, NULL, XML_PARSE_NOWARNING);

	if (!doc) {
		fprintf(stderr, "service.c: configuration file doesn't exist\n");
		return 1;
	}

	root = xmlDocGetRootElement(doc);
	parameter = root ->children;

	while (parameter) {
		if (xmlStrEqual(xmlGetProp(parameter, "name"), name)) {
			*value = atoi(xmlGetProp(parameter, "value"));
			break;
		}
		parameter = parameter->next;
	}

	xmlFreeDoc(doc);

	return 0;
}

int get_simple_name(char ** target) {

	xmlDoc * doc = xmlReadDoc(*target, NULL, NULL, XML_PARSE_NOWARNING);
	if (doc) {
		xmlNode * node = xmlDocGetRootElement(doc);
		if (node) {
			strcpy(*target, xmlGetProp(node, "value"));
		}
	}
	xmlFreeDoc(doc);

	return 0;
}

int get_time_string(char **time_string) {
	time_t curtime;
	struct tm *loctime;
	curtime = time(NULL);
	loctime = localtime(&curtime);
	char * dateTime = asctime(loctime);
	*time_string = malloc(256);
	strncpy(*time_string, dateTime, strlen(dateTime) - 1);
	return 0;
}
